# -*- coding: UTF-8 -*-
__author__ = 'czyigy'
import binascii
from constant import *
import struct
from datetime import datetime as dt_date_time
import traceback
from logger import logger
from constant import get_alarm_info
import json

COMMAND_ERROR_TYPE = {
    0: 'send cmd success!',
    1: 'functon code error',
    2: 'pdu error',
    3: 'data lenhgt error',
    4: 'read/write register error',
    5: 'send crc error',
    6: 'receive crc error'
}

class UnPackData():
    def __init__(self):
        self.buffer = []

        self.SystemInfo = {
            'voltage': 0,
            'electricity': 0,
            'temperate': 0,
            }

        self.LampInfo ={
            'voltage': 0,
            'electricity': 0,
            'temperate': 0,
            'brightness_per': 0,
            'status': 0,
            'electric_status': 0,
            'power': 0,
            }

        self.SolarInfo = {
            'voltage': 0,
            'electricity': 0,
            'power': 0,
            }

        self.BatteryInfo ={
            'status': 0,
            'charge_status':0,
            'voltage': 0,
            'charge_electricity': 0,
            'discharge_electricity': 0,
            'charge_power': 0,
            'discharge_power': 0,
            'temperate': 0,
            'all_electric_quantity': 0,
            'surplus_electric_quantity': 0,
            'soc': 0,
            'charge_electric_quantity': 0,
            'discharge_electric_quantity': 0,
            'charge_max_power': 0,
            'discharge_max_power': 0,
            }

        self.DailyEQInfo = {
            'electric_quantity_production': 0,
            'electric_quantity_consumption': 0,
            }

        self.ProductInfo ={
            'product_type': '',
            'product_software_version': '',
            'product_hardware_version': '',
            'product_sequence': '',
            }

        self.AlarmInfo = {
            'alarm_type': 0,
            }

        self.HistoryInfo = {
            'run_days': 0,
            'battery_over_discharge_times': 0,
            'battery_full_charge_times': 0,
            'battery_min_voltage': 0,
            'battery_max_voltage': 0,
        }

        self.BatterySettingInfo ={
            'capacity': 0,
            'vovervoltage':0,
            'vlimitedcharge': 0,
            'vbalancecharge': 0,
            'vpromotecharge': 0,
            'vfloatingcharge': 0,
            'vpromoterecover': 0,
            'voverdischargerecover': 0,
            'vundervoltagewarn': 0,
            'voverdischarge': 0,
            'balancechargetime': 0,
            'promotechargetime': 0,
            'balanceinterval': 0,
            'tempcompensation': 0,
            'tempcompmax': 0,
            'tempcompmin': 0,
            'turnfloatingcurrent': 0,
            }

        self.LoadParamSettingInfo ={
            'workmode': 0,
            'worktimefirst': 0,
            'workpowerfirst': 0,
            'worktimesencond': 0,
            'workpowersencond': 0,
            'worktimethird': 0,
            'workpowerthird': 0,
            'worktimeforth': 0,
            'workpowerforth': 0,
            'voptically': 0,
            'delaytime': 0,
            'ledloadcurrent': 0,
            'powercmd': 0,
            'switchfeature': 0
            }

        self.Flag = 3
        self.MAC = 0
        self.VerifyCode = 0
        self.PDU = 0
        self.DataLength = 0
        self.lighteness = 0
        self.lampstatus = 0
        self.electric_supply_status = 0

        self.all_data = {
            'time':'',
            'MAC':self.MAC,
            'flag':self.Flag,
            'VerifyCode':self.VerifyCode,
            'PDU':self.PDU,
            'DataLength':self.DataLength,
            'HistoryInfo':self.HistoryInfo,
            'AlarmInfo':self.AlarmInfo,
            'ProductInfo':self.ProductInfo,
            'DailyEQInfo':self.DailyEQInfo,
            'BatteryInfo':self.BatteryInfo,
            'SolarInfo':self.SolarInfo,
            'LampInfo':self.LampInfo,
            'SystemInfo':self.SystemInfo
        }

    def init_data(self):
        self.SystemInfo = {
            'voltage': 0,
            'electricity': 0,
            'temperate': 0,
            }

        self.LampInfo ={
            'voltage': 0,
            'electricity': 0,
            'temperate': 0,
            'brightness_per': 0,
            'status': 0,
            'electric_status': 0,
            'power': 0,
            }

        self.SolarInfo = {
            'voltage': 0,
            'electricity': 0,
            'power': 0,
            }

        self.BatteryInfo ={
            'status': 0,
            'charge_status':0,
            'voltage': 0,
            'charge_electricity': 0,
            'discharge_electricity': 0,
            'charge_power': 0,
            'discharge_power': 0,
            'temperate': 0,
            'all_electric_quantity': 0,
            'surplus_electric_quantity': 0,
            'soc': 0,
            'charge_electric_quantity': 0,
            'discharge_electric_quantity': 0,
            'charge_max_power': 0,
            'discharge_max_power': 0,
            'charge_min_electricity': 0,
            'charge_max_electricity': 0,
            'discharge_min_electricity': 0,
            'discharge_max_electricity': 0,
            'min_temperate': 0,
            'max_temperate': 0,
            'battery_min_voltage': 0,
            'battery_max_voltage': 0,
            }

        self.DailyEQInfo = {
            'electric_quantity_production': 0,
            'electric_quantity_consumption': 0,
            'total_electric_quantity_production':0,
            "total_electric_quantity_consumption":0
            }

        self.ProductInfo ={
            'product_type': '',
            'product_software_version': '',
            'product_hardware_version': '',
            'product_sequence': '',
            }

        self.AlarmInfo = {
            'alarm_type': 0,
            'str_alarm_type':''
            }

        self.HistoryInfo = {
            'run_days': 0,
            'battery_over_discharge_times': 0,
            'battery_full_charge_times': 0,
            'totalchargeah': 0,
            'totaldischarah': 0,
        }

        self.BatterySettingInfo ={
            'capacity': 0,
            'vovervoltage':0,
            'vlimitedcharge': 0,
            'vbalancecharge': 0,
            'vpromotecharge': 0,
            'vfloatingcharge': 0,
            'vpromoterecover': 0,
            'voverdischargerecover': 0,
            'vundervoltagewarn': 0,
            'voverdischarge': 0,
            'balancechargetime': 0,
            'promotechargetime': 0,
            'balanceinterval': 0,
            'tempcompensation': 0,
            'tempcompmax': 0,
            'tempcompmin': 0,
            'turnfloatingcurrent': 0,
            }

        self.LoadParamSettingInfo ={
            'workmode': 0,
            'worktimefirst': 0,
            'workpowerfirst': 0,
            'worktimesencond': 0,
            'workpowersencond': 0,
            'worktimethird': 0,
            'workpowerthird': 0,
            'worktimeforth': 0,
            'workpowerforth': 0,
            'voptically': 0,
            'delaytime': 0,
            'ledloadcurrent': 0,
            'powercmd': 0,
            'switchfeature': 0
            }

        self.Flag = 3
        self.MAC = 0
        self.VerifyCode = 0
        self.PDU = 0
        self.DataLength = 0
        self.lighteness = 0
        self.lampstatus = 0
        self.electric_supply_status = 0

        self.all_data = {
            'time':'',
            'MAC':self.MAC,
            'flag':self.Flag,
            'VerifyCode':self.VerifyCode,
            'PDU':self.PDU,
            'DataLength':self.DataLength,
            'HistoryInfo':self.HistoryInfo,
            'AlarmInfo':self.AlarmInfo,
            'ProductInfo':self.ProductInfo,
            'DailyEQInfo':self.DailyEQInfo,
            'BatteryInfo':self.BatteryInfo,
            'SolarInfo':self.SolarInfo,
            'LampInfo':self.LampInfo,
            'SystemInfo':self.SystemInfo
        }

    #---------------basic function-----------------#
    def BYTEToString(self, Src):
        return str(binascii.b2a_hex(Src))

    def BYTEToInt(self,Src):
        return int(binascii.b2a_hex(Src),16)

    def WordToInt(self,Src):
        return int(binascii.b2a_hex(Src),16)

    def DWordToInt(self,Src):
        return int(binascii.b2a_hex(Src),16)

    def StringToInt(self,Src):
        return_val = 0
        for i,element in enumerate(Src):
            if element == 'A' or  element == 'a':
                return_val += 10*(16**(7-i))
            elif element == 'B' or  element == 'b':
                return_val += 11*(16**(7-i))
            elif element == 'C' or  element == 'c':
                return_val += 11*(16**(7-i))
            elif element == 'D' or  element == 'd':
                return_val += 13*(16**(7-i))
            elif element == 'E' or  element == 'e':
                return_val += 14*(16**(7-i))
            elif element == 'F' or  element == 'f':
                return_val += 15*(16**(7-i))
            else:
                return_val += int(element)*(16**(7-i))
        return return_val

    def DecodeVoltage(self,Src):
        voltage = self.WordToInt(Src)
        return round(voltage/10.00,2)

    def DecodeElectricity(self,Src):
        electricity = self.WordToInt(Src)
        return round(electricity/100.000,3)

    def DecodePower(self,Src):
        power = self.WordToInt(Src)
        return round(power/10.0,1)

    def DecodeSystemVoltage(self,Src):
        voltage = self.BYTEToInt(Src)
        return voltage

    def DecodeSystemElectricity(self,Src):
        electricity = self.BYTEToInt(Src)
        return electricity

    def DecodeTemperate(self,Src):
        temperate = self.BYTEToInt(Src)
        if temperate>>7 == 1:
            temperate = -(temperate-128)
        return temperate

    def DecodeStatus(self,Src):
        status = self.BYTEToInt(Src)
        return status

    #battery
    def DecodeElectricQuantity(self,Src):
        if len(Src)  == 2:
            return self.WordToInt(Src)
        else:
            return self.DWordToInt(Src)

    #electric_energy
    def DecodeElectricEnergy(self,Src):
        if len(Src)  == 2:
            electric_energy = self.WordToInt(Src)
        else:
            electric_energy = self.DWordToInt(Src)
        return round(electric_energy/10.0,1)

    def DecodeSOC(self,Src):
        return self.DWordToInt(Src)

    def DecodeRunDays(self,Src):
        return self.BYTEToInt(Src)


    def DecodeTimes(self,Src):
        return self.WordToInt(Src)


    def DecodeAlarmType(self,Src):
        alarm_value = self.DWordToInt(Src)
        self.electric_supply_status = 0

        if alarm_value & 0x40:
            self.electric_supply_status = 1

        self.LampInfo['electric_status'] = self.electric_supply_status

        alarm_value = alarm_value &0xFFFFADBF
        return alarm_value


    def DecodeProductType(self,Src):
        product_type = ""
        for item in Src:
            product_type += self.BYTEToString(item)
        return product_type

    def DecodeProductVersion(self,Src):
        version = ""
        for item in Src:
            version += self.BYTEToString(item)
        return version

    def DecodeSequence(self,Src):
        sequence = ""
        for item in Src:
            sequence += self.BYTEToString(item)
        return sequence


    #---------------info function-----------------#

    def DecodeSystemInfo(self,Src):
        try:
            self.SystemInfo['voltage'] = self.DecodeSystemVoltage(Src[0])
            self.SystemInfo['electricity'] = self.DecodeSystemElectricity(Src[1])
            self.SystemInfo['temperate'] = self.DecodeTemperate(Src[2])
        except:
            return False
        return True

    def DecodeLampInfo(self,Src):
        try:
            lamp_status = self.DecodeStatus(Src[0])
            #logger.info("bbbb")
            #logger.info(lamp_status)
            self.LampInfo['status'] = lamp_status>>7 & 1
            #logger.info("cccc")
            #logger.info(self.LampInfo['status'])
            #logger.info("###lampInfo##")
            #logger.info(self.LampInfo['status'])
            self.LampInfo['brightness_per'] = lamp_status & 127
            self.LampInfo['voltage'] = self.DecodeVoltage(Src[1:3])
            self.LampInfo['electricity'] = self.DecodeElectricity(Src[3:5])
            self.LampInfo['power'] = round(self.LampInfo['voltage']*self.LampInfo['electricity'],2)
            self.LampInfo['temperate'] = self.DecodeTemperate(Src[5])
        except:
            return False
        return True

    def DecodeSolarInfo(self,Src):
        try:
            self.SolarInfo['voltage'] = self.DecodeVoltage(Src[0:2])
            self.SolarInfo['electricity'] = self.DecodeElectricity(Src[2:4])
            self.SolarInfo['power'] = round(self.SolarInfo['voltage']*self.SolarInfo['electricity'],2)
        except:
            return False
        return True

    def DecodeBatteryInfo(self,Src):
        try:
            status = self.DecodeStatus(Src[0])
            self.BatteryInfo['status'] = status & 15
            self.BatteryInfo['charge_status'] = status & 240
            self.BatteryInfo['voltage'] = self.DecodeVoltage(Src[1:3])
            self.BatteryInfo['charge_electricity'] = self.DecodeElectricity(Src[3:5])
            self.BatteryInfo['discharge_electricity'] = self.DecodeElectricity(Src[5:7])
            self.BatteryInfo['charge_power'] = self.BatteryInfo['voltage']*self.BatteryInfo['charge_electricity']
            self.BatteryInfo['discharge_power'] = self.BatteryInfo['voltage']*self.BatteryInfo['discharge_electricity']
            self.BatteryInfo['temperate'] = self.DecodeTemperate(Src[7])
            self.BatteryInfo['all_electric_quantity'] = self.DecodeElectricQuantity(Src[8:10])
            self.BatteryInfo['surplus_electric_quantity'] = self.DecodeElectricQuantity(Src[10:12])
            self.BatteryInfo['soc'] = self.DecodeSOC(Src[12])
            self.BatteryInfo['battery_min_voltage'] = self.DecodeVoltage(Src[13:15])
            self.BatteryInfo['battery_max_voltage'] = self.DecodeVoltage(Src[15:17])
            self.BatteryInfo['charge_electric_quantity'] = self.DecodePower(Src[17:19])
            self.BatteryInfo['discharge_electric_quantity'] = self.DecodePower(Src[19:21])
            self.BatteryInfo['charge_max_power'] = self.DecodePower(Src[21:23])
            self.BatteryInfo['discharge_max_power'] = self.DecodePower(Src[23:25])
            self.BatteryInfo['charge_min_electricity'] = self.WordToInt(Src[25:27])
            self.BatteryInfo['charge_max_electricity'] = self.DecodeElectricity(Src[27:29])
            self.BatteryInfo['discharge_min_electricity'] = self.WordToInt(Src[29:31])
            self.BatteryInfo['discharge_max_electricity'] = self.DecodeElectricity(Src[31:33])
            self.BatteryInfo['min_temperate'] = self.DecodeTemperate(Src[33])
            self.BatteryInfo['max_temperate'] = self.DecodeTemperate(Src[34])
        except:
            return False
        return True

    def DecodeBatterySettingInfo(self,Src):
        try:
            tempcompmin = self.BYTEToInt(Src[25:26])
            if self.DataLength == 28:
                self.BatterySettingInfo['capacity'] = self.WordToInt(Src[0:2])
                self.BatterySettingInfo['vovervoltage'] = round(self.WordToInt(Src[2:4])/10.00,2)
                self.BatterySettingInfo['vlimitedcharge'] = round(self.WordToInt(Src[4:6])/10.00,2)
                self.BatterySettingInfo['vbalancecharge'] = round(self.WordToInt(Src[6:8])/10.00,2)
                self.BatterySettingInfo['vpromotecharge'] = round(self.WordToInt(Src[8:10])/10.00,2)
                self.BatterySettingInfo['vfloatingcharge'] = round(self.WordToInt(Src[10:12])/10.00,2)
                self.BatterySettingInfo['vpromoterecover'] = round(self.WordToInt(Src[12:14])/10.00,2)
                self.BatterySettingInfo['voverdischargerecover'] = round(self.WordToInt(Src[14:16])/10.00,2)
                self.BatterySettingInfo['vundervoltagewarn'] = round(self.WordToInt(Src[16:18])/10.00,2)
                self.BatterySettingInfo['voverdischarge'] = round(self.WordToInt(Src[18:20])/10.00,2)
                self.BatterySettingInfo['balancechargetime'] = self.BYTEToInt(Src[20:21])
                self.BatterySettingInfo['promotechargetime'] = self.BYTEToInt(Src[21:22])
                self.BatterySettingInfo['balanceinterval'] = self.BYTEToInt(Src[22:23])
                self.BatterySettingInfo['tempcompensation'] = self.BYTEToInt(Src[23:24])
                self.BatterySettingInfo['tempcompmax'] = self.BYTEToInt(Src[24:25])
                if tempcompmin > 0x7f:
                    self.BatterySettingInfo['tempcompmin'] = -(tempcompmin&0x7f)
                else:
                    self.BatterySettingInfo['tempcompmin'] = tempcompmin
                self.BatterySettingInfo['turnfloatingcurrent'] = round(self.WordToInt(Src[26:28])/100.000,3)
                self.BatterySettingInfo['batterytype'] = 0
                self.BatterySettingInfo['vsystem'] = 0
                self.BatterySettingInfo['minusnocharge'] = 0
                self.BatterySettingInfo['chargemode'] = 0
            elif self.DataLength == 32:
                self.BatterySettingInfo['capacity'] = self.WordToInt(Src[0:2])
                self.BatterySettingInfo['vovervoltage'] = round(self.WordToInt(Src[2:4])/10.00,2)
                self.BatterySettingInfo['vlimitedcharge'] = round(self.WordToInt(Src[4:6])/10.00,2)
                self.BatterySettingInfo['vbalancecharge'] = round(self.WordToInt(Src[6:8])/10.00,2)
                self.BatterySettingInfo['vpromotecharge'] = round(self.WordToInt(Src[8:10])/10.00,2)
                self.BatterySettingInfo['vfloatingcharge'] = round(self.WordToInt(Src[10:12])/10.00,2)
                self.BatterySettingInfo['vpromoterecover'] = round(self.WordToInt(Src[12:14])/10.00,2)
                self.BatterySettingInfo['voverdischargerecover'] = round(self.WordToInt(Src[14:16])/10.00,2)
                self.BatterySettingInfo['vundervoltagewarn'] = round(self.WordToInt(Src[16:18])/10.00,2)
                self.BatterySettingInfo['voverdischarge'] = round(self.WordToInt(Src[18:20])/10.00,2)
                self.BatterySettingInfo['balancechargetime'] = self.BYTEToInt(Src[20:21])
                self.BatterySettingInfo['promotechargetime'] = self.BYTEToInt(Src[21:22])
                self.BatterySettingInfo['balanceinterval'] = self.BYTEToInt(Src[22:23])
                self.BatterySettingInfo['tempcompensation'] = self.BYTEToInt(Src[23:24])
                self.BatterySettingInfo['tempcompmax'] = self.BYTEToInt(Src[24:25])
                if tempcompmin > 0x7f:
                    self.BatterySettingInfo['tempcompmin'] = -(tempcompmin&0x7f)
                else:
                    self.BatterySettingInfo['tempcompmin'] = tempcompmin
                self.BatterySettingInfo['turnfloatingcurrent'] = round(self.WordToInt(Src[26:28])/100.000,3)
                self.BatterySettingInfo['batterytype'] = self.BYTEToInt(Src[28:29])
                self.BatterySettingInfo['vsystem'] = self.BYTEToInt(Src[29:30])
                self.BatterySettingInfo['minusnocharge'] = self.BYTEToInt(Src[30:31])
                self.BatterySettingInfo['chargemode'] = self.BYTEToInt(Src[31:32])
        except:
            return False
        return True

    def DecodeLoadParamSettingInfo(self,Src):
        try:
            self.LoadParamSettingInfo['workmode'] = self.BYTEToInt(Src[0:1])
            self.LoadParamSettingInfo['worktimefirst'] = self.BYTEToInt(Src[1:2])
            self.LoadParamSettingInfo['workpowerfirst'] = self.BYTEToInt(Src[2:3])
            self.LoadParamSettingInfo['worktimesencond'] = self.BYTEToInt(Src[3:4])
            self.LoadParamSettingInfo['workpowersencond'] = self.BYTEToInt(Src[4:5])
            self.LoadParamSettingInfo['worktimethird'] = self.BYTEToInt(Src[5:6])
            self.LoadParamSettingInfo['workpowerthird'] = self.BYTEToInt(Src[6:7])
            self.LoadParamSettingInfo['worktimeforth'] = self.BYTEToInt(Src[7:8])
            self.LoadParamSettingInfo['workpowerforth'] = self.BYTEToInt(Src[8:9])
            self.LoadParamSettingInfo['delaytime'] = self.BYTEToInt(Src[9:10])
            self.LoadParamSettingInfo['voptically'] = round(self.WordToInt(Src[10:12])/10.00,2)
            self.LoadParamSettingInfo['ledloadcurrent'] = self.WordToInt(Src[12:14])
            self.LoadParamSettingInfo['powercmd'] = self.BYTEToInt(Src[14:15])
            self.LoadParamSettingInfo['switchfeature'] = self.BYTEToInt(Src[15:16])
            #logger.info(" self.LoadParamSettingInfo %s"%str(self.LoadParamSettingInfo))
        except:
            return False
        return True

    def DecodeDailyElectricQuantity(self,Src):
        try:
            self.DailyEQInfo['electric_quantity_production'] = self.DecodeElectricEnergy(Src[0:2])
            self.DailyEQInfo['electric_quantity_consumption'] = self.DecodeElectricEnergy(Src[2:4])
            self.DailyEQInfo['total_electric_quantity_production'] = self.DecodeElectricEnergy(Src[4:8])
            self.DailyEQInfo['total_electric_quantity_consumption'] = self.DecodeElectricEnergy(Src[8:12])
        except:
            return False
        return True

    def DecodeHistoryInfo(self,Src):
        try:
            self.HistoryInfo['run_days'] = self.DecodeRunDays(Src[0:2])
            self.HistoryInfo['battery_over_discharge_times'] = self.DecodeTimes(Src[2:4])
            self.HistoryInfo['battery_full_charge_times'] = self.DecodeTimes(Src[4:6])
            self.HistoryInfo['totalchargeah'] = self.BatteryInfo.get("charge_electric_quantity",0)
            self.HistoryInfo['totaldischarah'] = self.BatteryInfo.get("discharge_electric_quantity",0)
        except:
            return False
        return True

    def DecodeAlarmInfo(self,Src):
        try:
            self.AlarmInfo['alarm_type'] = self.DecodeAlarmType(Src)
            self.AlarmInfo['str_alarm_type'] = get_alarm_info(self.AlarmInfo['alarm_type'])
            #self.AlarmInfo['alarm_type'] = 1
            #self.AlarmInfo['str_alarm_type'] = get_alarm_info(self.AlarmInfo['alarm_type'])
            #logger.info("this is the debug place...")
            #logger.info(self.AlarmInfo)
        except:
            return False
        else:
            return True


    def DecodeProductInfo(self,Src):
        try:
            self.ProductInfo['product_type'] = self.DecodeProductType(Src[0:16])
            self.ProductInfo['product_software_version'] = self.DecodeProductVersion(Src[16:19])
            self.ProductInfo['product_hardware_version'] = self.DecodeProductVersion(Src[19:22])
            self.ProductInfo['product_sequence'] = self.DecodeSequence(Src[22:26])
        except:
            return False
        else:
            return True

    def DecodeChangeChannelResp(self,Src):

            return True

    def DecodeFlag(self,Src):
        flag = self.BYTEToInt(Src)
        return flag

    def DecodeMAC(self,Src):
        sMac = self.DWordToInt(Src)
        return sMac

    def DecodeVerifyCode(self,Src):
        return self.BYTEToInt(Src)

    def DecodePDU(self,Src):
        return self.WordToInt(Src)

    def DecodeCompleteMsg(self,Src):
        self.init_data()
        try:
            error_msg = "unknown"
            self.MAC = self.DecodeMAC(Src[0:4])
            self.Flag = self.DecodeFlag(Src[4])
            if get_read_length(Src[5:7]) <= 0:
                logger.error("PDU error")
                error_msg = "PDU error"
                return (False,error_msg,self.Flag,-1, -1)
            self.PDU = self.DecodePDU(Src[5:7])
            self.DataLength = self.BYTEToInt(Src[7])
            data_end = self.DataLength + 8
            check_code = 0
            if self.Flag == 0x80:
                errorType = self.BYTEToInt(Src[7])
                return (False, COMMAND_ERROR_TYPE[errorType], self.Flag, self.PDU, self.MAC)
            #logger.info("PDU %d", self.PDU)
            if self.Flag != 3:
                data_end = len(Src) -1
            for data in Src[5:data_end]:
                item , = struct.unpack('B',data)
                check_code += item
            check_code, = struct.unpack('B',struct.pack('I',check_code)[0])
            self.VerifyCode = self.DecodeVerifyCode(Src[data_end])

            if check_code != self.VerifyCode:
                error_msg = 'error check_code %s  %s'%(check_code, self.VerifyCode)
                logger.error(error_msg)
                return (False,error_msg,self.Flag,self.PDU, self.MAC)

            if self.Flag != 3:

                if self.Flag not in [3,6,16]:
                    item, = struct.unpack('B',Src[7])
                    error_msg = "command error error code is %s"%item
                    result = False
                else:
                    error_msg = "decode write register %s" % self.PDU
                    result = True
                    if self.PDU == 0x300:
                        self.lampstatus = self.DecodeFlag(Src[7])

                    elif self.PDU == 0x304:
                        self.lighteness = (self.DecodeFlag(Src[7])&0x7f)

                    elif self.PDU == 0x305:
                        self.electric_supply_status = self.DecodeFlag(Src[7])

                #logger.info(error_msg)
                return (result,error_msg,self.Flag,self.PDU, self.MAC)

            if self.PDU == 0 and self.DataLength == 70:
                self.DecodeSystemInfo(Src[8:11])
                self.DecodeLampInfo(Src[11:17])
                self.DecodeSolarInfo(Src[17:21])
                self.DecodeBatteryInfo(Src[21:56])
                self.DecodeDailyElectricQuantity(Src[56:68])
                self.DecodeHistoryInfo(Src[68:74])
                self.DecodeAlarmInfo(Src[74:data_end])
                self.PDU = 70
                #logger.info(self.all_data)

            elif self.PDU == 0:
                self.DecodeSystemInfo(Src[8:data_end])

            elif self.PDU == 3:
                self.DecodeLampInfo(Src[8:data_end])

            elif self.PDU == 9:
                self.DecodeSolarInfo(Src[8:data_end])

            elif self.PDU == 13:
                self.DecodeBatteryInfo(Src[8:data_end])

            elif self.PDU == 48:
                self.DecodeDailyElectricQuantity(Src[8:data_end])

            elif self.PDU == 60:
                self.DecodeHistoryInfo(Src[8:data_end])

            elif self.PDU == 66:
                self.DecodeAlarmInfo(Src[8:data_end])

            elif self.PDU == 512:
                self.DecodeProductInfo(Src[8:data_end])

            elif self.PDU == 784:
                self.DecodeChangeChannelResp(Src[8:data_end])

            elif self.PDU == 808:
                self.DecodeBatterySettingInfo(Src[8:data_end])

            elif self.PDU == 1024:
                self.DecodeLoadParamSettingInfo(Src[8:data_end])

            self.all_data = {
                'time':dt_date_time.now().strftime('%Y-%m-%d %H:%M:%S'),
                'MAC':self.MAC,
                'flag':self.Flag,
                'VerifyCode':self.VerifyCode,
                'PDU':self.PDU,
                'DataLength':self.DataLength,
                'HistoryInfo':self.HistoryInfo,
                'AlarmInfo':self.AlarmInfo,
                'ProductInfo':self.ProductInfo,
                'DailyEQInfo':self.DailyEQInfo,
                'BatteryInfo':self.BatteryInfo,
                'SolarInfo':self.SolarInfo,
                'LampInfo':self.LampInfo,
                'SystemInfo':self.SystemInfo
            }
        except:
            error_msg = "decode error, length of buffer is not enough"
            logger.error(error_msg)
            return (False,error_msg,self.Flag,self.PDU, self.MAC)
        return (True,'success',self.Flag,self.PDU, self.MAC)

    @staticmethod
    def get_json_format(raw_msg):
        #logger.error("type raw_msg: %s" % type(raw_msg))
        #logger.error("raw_msg: %s" % str(raw_msg))

        try:
            msg = json.loads(raw_msg, encoding='utf-8')
            #logger.info("json decode: %s" % str(msg))
            return True, msg
        except Exception, e:
            #logger.error("json decode error: %s" % str(e))
            return False, None


